/**
 * rommanager.h
 * General ROM identication/loading routines.
 *
 * @author  Philippe Johnson
 */

#ifndef __ROMMANAGER_H__
#define __ROMMANAGER_H__

#include "common.h"
#include "assert.h"

#define LOROMOFFSET            32704
#define HIROMOFFSET            65472
#define INVCHECKSUMOFFSET      28
#define CHECKSUMOFFSET         30

#define ROMHEADER_SIZE         512

/* ROM speed */
#define ROMSPEED_SLOWROM       0
#define ROMSPEED_FASTROM       3

/* ROM type constants */
#define ROMTYPE_ROMONLY        0
#define ROMTYPE_ROMRAM         1
#define ROMTYPE_ROMSRAM        2
#define ROMTYPE_ROMDSP1        3
#define ROMTYPE_ROMRAMDSP      4
#define ROMTYPE_ROMSRAMDSP     5
#define ROMTYPE_ROMSFX         19
#define ROMTYPE_ROMRAMGB       227
#define ROMTYPE_ROMDSP2        246

/* ROM size constants - 
 * shl ROMbyte-7 MBits works too, but this is more readable imho */
#define ROMSIZE_2MBITS         8
#define ROMSIZE_4MBITS         9
#define ROMSIZE_8MBITS         10
#define ROMSIZE_16MBITS        11
#define ROMSIZE_32MBITS        12

/* SROM size constants */
#define SRAMSIZE_NONE          0
#define SRAMSIZE_16KBITS       1
#define SRAMSIZE_32KBITS       2
#define SRAMSIZE_64KBITS       3

/* Country codes */
#define ROMCTRY_JAPAN          0  /* NTSC */
#define ROMCTRY_USA            1
#define ROMCTRY_AUSTRALIA      2  /* PAL */
#define ROMCTRY_SWEDEN         3
#define ROMCTRY_FINLAND        4
#define ROMCTRY_DENMARK        5
#define ROMCTRY_FRANCE         6
#define ROMCTRY_HOLLAND        7
#define ROMCTRY_SPAIN          8
#define ROMCTRY_GERMANY        9
#define ROMCTRY_ITALY          10
#define ROMCTRY_CHINA          11
#define ROMCTRY_INDONESIA      12
#define ROMCTRY_KOREA          13

/* License code */
#define ROMLICENSE_NINTENDO    1
#define ROMLICENSE_IMAGINEZ    3
#define ROMLICENSE_ZAMUSE      5
#define ROMLICENSE_FALCOM      6
#define ROMLICENSE_CAPCOM      8
#define ROMLICENSE_HOTB        9
#define ROMLICENSE_JALECO      10
#define ROMLICENSE_COCONUTS    11
#define ROMLICENSE_RAGE        12
#define ROMLICENSE_TECHNOS     14
#define ROMLICENSE_MEBIO       15
#define ROMLICENSE_GREMLIN     18
#define ROMLICENSE_EA          19
#define ROMLICENSE_COBRA       21
#define ROMLICENSE_HUMAN       22
#define ROMLICENSE_KOEI        23
#define ROMLICENSE_HUDSON      24
#define ROMLICENSE_YANOMAN     26
#define ROMLICENSE_TECMO       28
#define ROMLICENSE_OPENSYS     30
#define ROMLICENSE_VIRGIN      31
#define ROMLICENSE_KSS         32
#define ROMLICENSE_SUNSOFT     33
#define ROMLICENSE_POW         34
#define ROMLICENSE_MICROWORLD  35
#define ROMLICENSE_ENIX        38
#define ROMLICENSE_LORICIEL    39
#define ROMLICENSE_KEMCO       40
/* TODO: complete list */

/* SWC header constants */
#define SWCIDENTIFIER          0xAABB04
#define SWCIMAGE_MODEMASK      ( 1 << 7 )
#define SWCIMAGE_IMAGEMASK     ( 1 << 6 )
#define SWCIMAGE_SRAMMODEMASK  ( 1 << 5 )
#define SWCIMAGE_DRAMMODEMASK  ( 1 << 4 )
#define SWCIMAGE_SRAMSIZE      ( 3 << 1 )

/* FIG header constants */
/* TODO */

typedef struct _RomInfo {
    u8  title[21];          /* The game title */
    u8  makeup;             /* [0-3] Bank size (Lo/Hi) [4-7] ROM speed */
    u8  type;               /* Type of ROM data */
    u8  size;               /* ROM size */
    u8  sramSize;           /* Size of SRAM */
    u8  country;            /* Country code */
    u8  license;            /* Company license code */
    u8  gameVersion;        /* ROM's version */
    u16 inverseChecksum;    /* Checksum bytes XORed */
    u16 checksum;           /* sum(bytes)... dur */
    u16 nmiVector;          /* Address of NMI code */
    u16 resetVector;        /* Entry point in ROM */
} RomInfo;

typedef struct _SWCHeader {
    u16 size;               /* ROM size */
    u8  imageInfo;          /* Image descriptor */
    u8  padding[5];
    u8  identAAh;           /* Must = 0xAA */
    u8  identBBh;           /* Must = 0xBB */
    u8  ident04h;           /* Must = 0x04 */
} SWCHeader;

typedef struct _FIGHeader {
    u16 size;               /* ROM size */
    u8  images;             /* Multi or single/last image */
    u8  romType;            /* Hi or Lo ROM */
    u8  sramInfo1;          /* SRAM/DSP information */
    u8  sramInfo2;          /* Same info, different constants...? */
} FIGHeader;

/* Enums for other modules */
typedef enum {
    HIROM, LOROM
} ROMTYPE;

typedef enum {
    SLOWROM, FASTROM
} ROMSPEED;

static void*   romData = 0; /* Pointer to ROM data */

/**
 * loadRom
 * Allocates the appropriate amount for romData and 
 * loads a ROM into memory.
 *
 * @param filename Name of the SNES ROM to load. Must point at
 *                 the beginning of the RomInfo structure.
 * @param romInfo  Pointer to a RomInfo structure to be filled out
 * @return TRUE if success, FALSE otherwise
 */
BOOL loadRom( char* filename, RomInfo* romInfo );

/**
 * unloadRom
 * Free ROM resources.
 */
void unloadRom();

/**
 * getRomData
 * Gets a pointer to the ROM data.
 *
 * @return romData
 */
void* getRomData();

#endif // __ROMMANAGER_H__
